package de.karlNet.sambamanager.ldapController;

import java.util.ArrayList;
import java.util.List;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;

import de.karlNet.sambamanager.ldapModel.LdapGroup;
import de.karlNet.sambamanager.ldapModel.LdapObject;
import de.karlNet.sambamanager.ldapModel.LdapUser;

public abstract class AbstractLdapTree {
	protected abstract LdapTemplate getLdapTemplate();

	private AttributesMapper attributesMapper = new AttributesMapper() {
		public Object mapFromAttributes(Attributes attributes)
				throws NamingException {
			LdapObject objectToReturn = null;
			String dn = "";
			if (attributes.get("distinguishedname") == null) {
				dn = (String) attributes.get("dn").get();
			} else {
				dn = (String) attributes.get("distinguishedname").get();
			}
			System.out.println("returning " + dn);
			String cn = "";
			if (attributes.get("name") == null) {
				cn = (String) attributes.get("cn").get();
			} else {
				cn = (String) attributes.get("name").get();
			}

			NamingEnumeration<?> objectclassEnum = attributes
					.get("objectclass").getAll();
			while (objectclassEnum.hasMore()) {
				String objectClass = (String) objectclassEnum.next();
				if (objectClass.equals("group")) {
					objectToReturn = new LdapGroup(cn, dn);
					break;
				} else if (objectClass.equals("user")) {
					objectToReturn = new LdapUser(cn, dn);
					break;
				}
			}
			String orignaldn = null;
			if (attributes.get("originaldn") != null) {
				orignaldn = (String) attributes.get("originaldn").get();
				objectToReturn.setOriginalDN(orignaldn);
			}

			if (objectToReturn == null) {
				objectToReturn = new LdapObject(cn, dn);
			}
			return objectToReturn;
		}
	};

	public LdapObject getNewDn(String originalDn) {
		System.out.println("(|(originaldn=" + originalDn + ")(dn=" + originalDn
				+ ")(distinguishedName=" + originalDn + "))");
		List ldapObjects = getLdapTemplate()
				.search("dc=example,dc=com",
						"(originaldn=" + originalDn + ")",
						SearchControls.SUBTREE_SCOPE,
						new String[] { "cn", "objectclass","originaldn",
								"distinguishedName", "dn" },
						this.attributesMapper);
		List<LdapObject> ret = new ArrayList<LdapObject>(ldapObjects);
		return ret.get(0);
	}

	public List<LdapObject> getChildrenOfDN(String dn) {
		System.out.println("querying " + dn);
		List ldapObjects = getLdapTemplate().search(
				dn,
				"(objectClass=*)",
				SearchControls.ONELEVEL_SCOPE,
				new String[] { "cn", "name", "objectclass", "originaldn",
						"distinguishedName", "dn" }, this.attributesMapper);
		List<LdapObject> ret = new ArrayList<LdapObject>(ldapObjects);
		return ret;
	}

	public LdapObject getObject(String dn) {
		System.out.println("querying " + dn);
		List ldapObjects = getLdapTemplate().search(
				dn,
				"(objectClass=*)",
				SearchControls.OBJECT_SCOPE,
				new String[] { "cn", "name", "objectclass", "originaldn",
						"distinguishedName", "dn" }, this.attributesMapper);
		List<LdapObject> ret = new ArrayList<LdapObject>(ldapObjects);
		return ret.get(0);
	}

}